package com.jyw.router.hospital.service.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jyw.router.common.core.domain.CommonResult;
import com.jyw.router.common.core.redis.RedisCache;
import com.jyw.router.common.core.redis.RedisKeyConstant;
import com.jyw.router.common.exception.ServiceException;
import com.jyw.router.common.utils.DateUtils;
import com.jyw.router.common.utils.StringUtils;
import com.jyw.router.hospital.domain.HospitalRegisterUser;
import com.jyw.router.hospital.domain.WxUser;
import com.jyw.router.hospital.domain.dto.HospitalDicDto;
import com.jyw.router.hospital.domain.vo.LoginMiniappVo;
import com.jyw.router.hospital.domain.vo.RegisterHospitalVo;
import com.jyw.router.hospital.service.IHospitalRegisterUserService;
import com.jyw.router.hospital.service.IWxUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import com.jyw.router.hospital.mapper.HospitalInfoMapper;
import com.jyw.router.hospital.domain.HospitalInfo;
import com.jyw.router.hospital.service.IHospitalInfoService;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

import static com.jyw.router.common.core.redis.RedisKeyConstant.HOSPITAL_INFO;
import static com.jyw.router.common.core.redis.RedisKeyConstant.USER_TOKEN;

/**
 * 医院服务信息Service业务层处理
 * 
 * @author shenjun
 * @date 2023-04-10
 */
@Service
@Slf4j
public class HospitalInfoServiceImpl extends ServiceImpl<HospitalInfoMapper,HospitalInfo> implements IHospitalInfoService
{
    @Autowired
    private HospitalInfoMapper hospitalInfoMapper;

    @Resource
    private IHospitalRegisterUserService hospitalUserService;

    @Resource
    private IWxUserService wxUserService;

    @Resource
    private RestTemplate restTemplate;

    @Resource
    private RedisCache redisCache;

    @Value("${wx.miniapp.login.basic}")
    private String BASIC_LOGIN_URL;

    @Value("${wx.miniapp.login.repair}")
    private String REPAIR_LOGIN_URL;

    /**
     * 查询医院服务信息
     * 
     * @param id 医院服务信息主键
     * @return 医院服务信息
     */
    @Override
    public HospitalInfo selectHospitalInfoById(Long id)
    {
        return hospitalInfoMapper.selectHospitalInfoById(id);
    }

    /**
     * 查询医院服务信息列表
     * 
     * @param hospitalInfo 医院服务信息
     * @return 医院服务信息
     */
    @Override
    public List<HospitalInfo> selectHospitalInfoList(HospitalInfo hospitalInfo)
    {
        return hospitalInfoMapper.selectHospitalInfoList(hospitalInfo);
    }

    /**
     * 新增医院服务信息
     * 
     * @param hospitalInfo 医院服务信息
     * @return 结果
     */
    @Override
    public int insertHospitalInfo(HospitalInfo hospitalInfo)
    {
        return hospitalInfoMapper.insertHospitalInfo(hospitalInfo);
    }

    /**
     * 修改医院服务信息
     * 
     * @param hospitalInfo 医院服务信息
     * @return 结果
     */
    @Override
    public int updateHospitalInfo(HospitalInfo hospitalInfo)
    {
        return hospitalInfoMapper.updateHospitalInfo(hospitalInfo);
    }

    /**
     * 批量删除医院服务信息
     * 
     * @param ids 需要删除的医院服务信息主键
     * @return 结果
     */
    @Override
    public int deleteHospitalInfoByIds(Long[] ids)
    {
        return hospitalInfoMapper.deleteHospitalInfoByIds(ids);
    }

    /**
     * 删除医院服务信息信息
     * 
     * @param id 医院服务信息主键
     * @return 结果
     */
    @Override
    public int deleteHospitalInfoById(Long id)
    {
        return hospitalInfoMapper.deleteHospitalInfoById(id);
    }

    @Override
    public HospitalInfo registerHospital(RegisterHospitalVo vo) {
        HospitalInfo info = vo.buildHospitalInfo();
        hospitalInfoMapper.insert(info);
        log.info("新增医院信息:{}",info);
        return info;
    }

    @Override
    public List<HospitalDicDto> dictList() {
        LambdaQueryWrapper<HospitalInfo> queryWrapper = new LambdaQueryWrapper<HospitalInfo>();
        queryWrapper.eq(HospitalInfo::getRecordState,1);
        return this.hospitalInfoMapper.selectList(queryWrapper).stream().map(data -> new HospitalDicDto(data)).collect(Collectors.toList());
    }

    @Override
    public HospitalInfo getHospitalByKey(HospitalInfo info) {
        LambdaQueryWrapper<HospitalInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(HospitalInfo::getServerKey,info.getServerKey())
                .eq(HospitalInfo::getServerSecret,info.getServerSecret());
        return getOne(queryWrapper);
    }

    @Override
    public CommonResult login(WxUser wxUser, String hospitalId, LoginMiniappVo loginVo) {
        HospitalInfo hospital = null;
        HospitalRegisterUser hospitalUser = hospitalUserService.getUserByPhone(wxUser.getPhone());
        if(StringUtils.isEmpty(hospitalId)){
            //不是扫科室码登录,首先获取用户是否注册
            if(ObjectUtils.isEmpty(hospitalUser)){
                //不存在注册用户信息
                throw new ServiceException("用户未在系统注册或被禁用,登录失败!");
            }
            //获取医院信息请求token
            hospital = getById(hospitalUser.getHospitalId());
            if(hospital.getRecordState()==0){
                throw new ServiceException("该医院信息被禁用,登录失败");
            }
            //正常登录
            return basicLogin(hospital,wxUser,loginVo);
        }else{
            hospital = getHospitalByServerKey(hospitalId);
            if(hospital.getRecordState()==0){
                throw new ServiceException("该医院信息被禁用,登录失败");
            }
            //判断激活的用户信息是否与报修的医院一致
            if(!ObjectUtils.isEmpty(hospitalUser)
                    &&hospitalUser.getRecordState().equals(1)
                    &&hospitalUser.getHospitalId().equals(hospital.getId())){
                return basicLogin(hospital,wxUser,loginVo);
            }else{
                //不一致走无码报修获取token
                return repairLogin(hospital,wxUser);
            }
        }

    }

    @Override
    public HospitalInfo getCache(Long id) {
        HospitalInfo hospital = redisCache.getCacheObject(HOSPITAL_INFO + id);
        if(ObjectUtils.isEmpty(hospital)){
            hospital = getById(id);
            if(ObjectUtils.isEmpty(hospital)){
                throw new ServiceException("代理失败,代理信息不存在");
            }
            redisCache.setCacheObject(HOSPITAL_INFO+id,hospital,30, TimeUnit.DAYS);
        }
        if(hospital.getRecordState()!=1){
            throw new ServiceException("代理失败,代理服务被禁用");
        }
        return hospital;
    }

    /**
     * 通过公钥获取医院信息
     * @return
     */
    private HospitalInfo getHospitalByServerKey(String serverKey){
        LambdaQueryWrapper<HospitalInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(HospitalInfo::getServerKey,serverKey);
        return getOne(queryWrapper);
    }

    /**
     * 正常登录获取token
     * @param hospital
     * @param user
     * @param vo
     * @return
     */
    private CommonResult basicLogin(HospitalInfo hospital, WxUser user, LoginMiniappVo vo){
        //设置认证
//        HttpHeaders headers = new HttpHeaders();
//        headers.add("accessKey",hospital.getServerKey());
//        headers.add("secretKey",hospital.getServerSecret());

        JSONObject req = new JSONObject();
        req.put("phonenumber",vo.getPhone());
        req.put("serverKey",hospital.getServerKey());
        req.put("serverSecret",hospital.getServerSecret());

//        HttpEntity httpEntity = new HttpEntity<>(req,headers);

        ResponseEntity<JSONObject> response = restTemplate.postForEntity(hospital.getServerUrl() + BASIC_LOGIN_URL, req, JSONObject.class);
        log.info("请求正常登录,返回结果:{}",response);
        JSONObject json = response.getBody();
        CommonResult result = json.to(CommonResult.class);
        if(result.getCode() != 200){
            throw new ServiceException(result.getMsg());
        }
//        result.setData(json.get("data"));
        //记录登录
        logLogin(user,hospital,json.getString("data"));
        return result;
    }

    private CommonResult repairLogin(HospitalInfo hospital, WxUser wxUser){
        JSONObject jsonObject = restTemplate.postForObject(hospital.getServerUrl() + REPAIR_LOGIN_URL, null, JSONObject.class);
        CommonResult result = jsonObject.to(CommonResult.class);
        result.setData(jsonObject.get("body"));
        //记录登录
//        logLogin(wxUser,hospital,jsonObject.getJSONObject("body"));
        return result;
    }

    /**
     * 记录最后一次登录
     * @param user
     * @param token
     */
    private void logLogin(WxUser user,HospitalInfo hospitalInfo,String token){
        WxUser updateUser = new WxUser() {{
            setId(user.getId());
            setLastLoginTime(DateUtils.getNowDate());
            setToken(token);
            setLastLoginHospitalId(hospitalInfo.getId());
        }};
        wxUserService.updateById(updateUser);
        if(!StringUtils.isEmpty(user.getToken())){
            redisCache.deleteObject(USER_TOKEN+user.getToken());
        }
    }

}
